package com.xwaf.platform.system.provider.serviceimpl.gateway;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xwaf.platform.common.api.constants.BusinessConstants;
import com.xwaf.platform.common.api.exception.BusinessRunTimeException;
import com.xwaf.platform.common.redis.util.TaskRedisUtil;
import com.xwaf.platform.system.api.service.gateway.CurrentLimitService;
import com.xwaf.platform.system.api.service.gateway.TokenService;

@Transactional(readOnly = true)
@Service("currentLimitService")
public class CurrentLimitServiceImpl implements CurrentLimitService {

	private static final Logger log = LoggerFactory.getLogger(CurrentLimitServiceImpl.class);

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Resource
	private RedisTemplate<String, Long> redisTemplate;

	@Autowired
	private TokenService tokenService;

	@Autowired
	TaskRedisUtil taskRedisUtil;

	@Override
	public void currentLimit(String uri, String uid, String deviceType, int limit, int limit1m, int clearTokenNum) {
		long now = taskRedisUtil.getTime();
		// 拿到当前秒的时间
		long nows = now / 1000;
		long minute = now / (1000 * 60);
		long date = now / (1000 * 60 * 60 * 24);
		long number = redisTemplate.boundValueOps("currentlimit:" + uid + ":" + uri + ":" + nows).increment(1);
		redisTemplate.expire("currentlimit:" + uid + ":" + uri + ":" + nows, 1, TimeUnit.SECONDS);
		if (number > limit) {
			long dateNumber = redisTemplate.boundValueOps("currentlimit:" + uid + ":" + uri + ":" + date).increment(1);
			redisTemplate.expire("currentlimit:" + uid + ":" + uri + ":" + date, 1, TimeUnit.DAYS);
			if (clearTokenNum >= 1 && dateNumber > clearTokenNum) {
				stringRedisTemplate.boundValueOps("blacklist:user:" + uid).set("1");
				stringRedisTemplate.expire("blacklist:user:" + uid, 3, TimeUnit.DAYS);
				// 判断是否已经超过token清除次数
				tokenService.clearToken(deviceType, uid);

				redisTemplate.delete("currentlimit:" + uid + ":" + uri + ":" + date);
			}
			throw new BusinessRunTimeException(BusinessConstants.FREQUENT_OPERATION.getMsg());
		}
		long minuteNumber = redisTemplate.boundValueOps("currentlimit:" + uid + ":" + uri + ":" + minute).increment(1);
		redisTemplate.expire("currentlimit:" + uid + ":" + uri + ":" + minute, 1, TimeUnit.MINUTES);
		if (limit1m > 0 && minuteNumber > limit1m) {
			long dateNumber = redisTemplate.boundValueOps("currentlimit:" + uid + ":" + uri + ":" + date).increment(1);
			redisTemplate.expire("currentlimit:" + uid + ":" + uri + ":" + date, 1, TimeUnit.DAYS);
			if (clearTokenNum >= 1 && dateNumber > clearTokenNum) {
				stringRedisTemplate.boundValueOps("blacklist:user:" + uid).set("1");
				stringRedisTemplate.expire("blacklist:user:" + uid, 3, TimeUnit.DAYS);
				// 判断是否已经超过token清除次数
				tokenService.clearToken(deviceType, uid);
				redisTemplate.delete("currentlimit:" + uid + ":" + uri + ":" + date);
			}
			throw new BusinessRunTimeException(BusinessConstants.FREQUENT_OPERATION.getMsg());
		}
	}
}
